<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>slidem</title>
    <style>
        html,body{
            padding: 0;
            margin: 0;
            overflow: hidden;
        }
        .slideout{
            height: var(--w, 300px);
            position: relative;
        }
        .slidec{
            position: absolute;
            --n: calc(var(--num) + 2);
            width: calc(100% * var(--n));
            height: 100%;
            display: flex;
            background: #416A7F;
            transform: translate3d(var(--cx), 0, 0);
            transition: transform linear var(--dur, .3s);
        }
        .slide-item{
            width: 100%;
            height: 100%;
            background: none no-repeat center/contain;
        }
        .slide-dotc{
            width: 100px;
            height: 27px;
            position: absolute;
            bottom: 0;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(255, 255, 255, .1);
            border-radius: 10px;
            list-style: none;
            margin: 0;
            padding: 0 15px;
            display: flex;
            box-sizing: border-box;
        }
        .slide-dot{
            flex: 1;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        .slide-dot::after{
            content: '';
            display: inline-block;
            width: 8px;
            height: 8px;
            background: #fff;
            border-radius: 50%;
        }
        .slide-dot.cur::after{
            background: #ff5000;
        }
    </style>
</head>
<body>
    <div class="slideout">
        <div class="slidec">
        </div>
        <ul class="slide-dotc"></ul>
    </div>
    <script>
        //缺陷 touchend 无法准确切换cur
        class slide{
            constructor(urls){
                this.out = document.querySelector('.slideout');
                this.con = document.querySelector('.slidec');
                this.dotc = document.querySelector('.slide-dotc');
                this.urls = urls;
                this.num = urls.length;
                this.cur = 0;
                this.cw = 0;
                this.itemw = 0;
                this.timer = null;

                this.init();
            }
            init(){
                let urls = this.urls;

                let dotTpl = urls.map((t,i) => {
                    return `<li i="${i}" class="slide-dot"></li>`
                }).join('');
                this.dotc.innerHTML = dotTpl;

                urls = [urls[this.num-1], ...urls, urls[0]];
                let slideTpl = urls.map((t,i) => {
                    let slideItemCls = i < 1 ? 'slide-item cur' : 'slide-item';
                    return `<a style="background-image: url(${t})" href="javascript:;" i="${i}" class="${slideItemCls}" class="slide-link"></a>`
                }).join('');
                this.con.innerHTML = slideTpl;

                this.con.style.setProperty('--num', this.num);
                
                this.cw = this.con.offsetWidth;
                this.itemw = this.cw / (this.num+2);

                this.setCur(1);

                let startcx = 0;
                let startx = 0;
                let curX = 0;
                let offsetX = 0;

                this.con.addEventListener("touchstart", e => {
                    this.con.style.setProperty('--dur', '0s');
                    startx = e.touches[0].clientX;
                    startcx = this.getX();
                    this.endTimer();
                });

                this.con.addEventListener("touchmove", e => {
                    offsetX = e.touches[0].clientX - startx;
                    let cx = startcx + offsetX;
                    // this.con.style.transform = `translate3d(${cx}px, 0, 0)`;
                    this.con.style.setProperty('--cx', `${cx}px`);
                });

                this.con.addEventListener("touchend", () => {
                    let cur = this.cur;
                    if(Math.abs(offsetX) > (this.itemw / 6)){
                        offsetX < 0 ? cur += 1 : cur -= 1;
                    }
                    this.slideNext(cur);
                    this.startTimer();
                });

                this.startTimer();
            }
            slideNext(cur){
                this.setCur(cur, '.3');

                let target;
                if(cur < 1){
                    target = this.num;
                }
                else if(cur > this.num){
                    target = 1;
                }
                if(target){
                    this.con.addEventListener('transitionend', e => {
                        this.setCur(target);
                    },{once:true})
                }
            }
            setCur(cur, time){
                time = time || 0;
                this.con.style.setProperty('--dur', `${time}s`);

                this.cur = cur;

                let cx = -this.itemw * cur;
                // this.con.style.transform = `translate3d(${cx}px, 0, 0)`;
                this.con.style.setProperty('--cx', `${cx}px`);
            
                this.con.style.setProperty('--cur', cur);
                this.con.querySelector('.cur')?.classList.remove('cur');
                this.con.children[cur-1]?.classList.add('cur');
                this.dotc.querySelector('.cur')?.classList.remove('cur');
                this.dotc.children[cur-1]?.classList.add('cur');
            }
            getX(){
                // let trans = this.con.style.transform;
                // let match = trans.match(/[^(]+?(?=px)/);
                // return match ? parseFloat(match[0]) : 0;
                let x =  this.con.style.getPropertyValue('--cx') || 0;
                return parseFloat(x);
            }
            startTimer(){
                this.timer = setInterval(() => {
                   let cur = this.cur;
                   this.slideNext(++cur);
                }, 3000);
            }
            endTimer(){
                clearInterval(this.timer);
            }
        }

        let urls = [
            "https://img.alicdn.com/imgextra/i1/6000000004995/O1CN01C6bfox1mllHPXxQnO_!!6000000004995-0-octopus.jpg",
            "https://img.alicdn.com/imgextra/i4/O1CN01GOlEEW1zidUliI8O7_!!6000000006748-2-tps-846-472.png",
            "https://img.alicdn.com/imgextra/i4/O1CN01LHWdyp1yvAidcNMDR_!!6000000006640-0-tps-846-472.jpg",
            "https://img.alicdn.com/imgextra/i4/O1CN01aTXsri1my7yg4CMpt_!!6000000005022-0-tps-846-472.jpg",
        ];

        new slide(urls);
    </script>
</body>
</html>

